package com.imooc.distributelockstock.service;

import com.imooc.distributelockstock.dao.StockDao;
import com.imooc.distributelockstock.entity.GoodsAndStockEntity;
import com.imooc.distributelockstock.lock.AbstractLock;
import com.imooc.distributelockstock.lock.RedisLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.List;

@Service
public class StockService {

    @Autowired
    private StockDao stockDao;
    @Autowired
    private StringRedisTemplate template;

    @Autowired
    private RedissonClient redissonClient;


    public String deductStock(Long goodsId, Integer count) {
        // 1.查询商品库存的数量
        Integer stock = stockDao.selectStockByGoodsId(goodsId);
        // 2.判断库存数量是否足够
        if (stock < count) {
            return "库存不足";
        }

        //3. 如果库存数量足够，那么就去扣减库存
        stockDao.updateStockByGoodsId(goodsId, stock - count);
        return "库存扣减成功";
    }


    public String deductStockOneUpdate(Long goodsId, Integer count) {
        Integer result = stockDao.updateStockByGoodsIdAndCount(goodsId, count);
        if(result >0){
            return "扣减库存成功";
        }
        return "库存不足";
    }

    @Transactional
    public String deductStockForUpdate(Long goodsId, Integer count) {
        // 1.查询商品库存的数量
        Integer stock = stockDao.selectStockByGoodsIdForUpdate(goodsId);
        // 2.判断库存数量是否足够
        if (stock < count) {
            return "库存不足";
        }

        //3. 如果库存数量足够，那么就去扣减库存
        stockDao.updateStockByGoodsId(goodsId, stock - count);
        return "库存扣减成功";
    }

    public String deductStockCAS(Long goodsId, Integer count) {
        Integer result = 0;
        while(result ==0){
            // 1.查询商品库存的数量+version
            List<GoodsAndStockEntity> goodsAndStockEntityList = stockDao.selectStockAndVersionByGoodsId(goodsId);

            if (CollectionUtils.isEmpty(goodsAndStockEntityList)) {
                return "商品不存在";
            }
            GoodsAndStockEntity goodsAndStockEntity = goodsAndStockEntityList.get(0);
            // 2.判断库存数量是否足够
            if(goodsAndStockEntity.getStock() < count){
                return "库存不足";
            }


            //3. 如果库存数量足够，那么就去扣减库存
            result = stockDao.updateStockAndVersionByGoodsIdAndVersion(goodsId, goodsAndStockEntity.getStock() - count,
                    goodsAndStockEntity.getVersion());
        }
        return "库存扣减成功";
    }

    public String deductStockRedis(Long goodsId,Integer count){
        //1. 查询商品库存的数量
        String stock = template.opsForValue().get("stock"+goodsId);
        if(StringUtils.isEmpty(stock)){
            return "商品不存在";
        }
        int lastStock = Integer.parseInt(stock);
        // 2.判断库存数量是否足够
        if(lastStock<count){
            return "库存不足";
        }
        // 3. 如果库存数量足够，那么就去扣减库存
        template.opsForValue().set("stock"+goodsId,String.valueOf(lastStock-count));
        return "库存扣减成功";
    }

    public String deductStockRedisLock(Long goodsId,Integer count){
        AbstractLock lock = null;

        try{
            lock = new RedisLock(template,"lock"+goodsId);
            lock.lock();
            Thread.sleep(20000);
            //1. 查询商品库存的数量
            String stock = template.opsForValue().get("stock"+goodsId);
            if(StringUtils.isEmpty(stock)){
                return "商品不存在";
            }
            int lastStock = Integer.parseInt(stock);
            // 2.判断库存数量是否足够
            if(lastStock<count){
                return "库存不足";
            }
            // 3. 如果库存数量足够，那么就去扣减库存
            template.opsForValue().set("stock"+goodsId,String.valueOf(lastStock-count));
            return "库存扣减成功";

        }catch (InterruptedException e){
            throw new RuntimeException();
        } finally {
            if(lock!=null){
                lock.unlock();
            }
        }

    }

    public String deductStockRedisRedisson(Long goodsId,Integer count){
        RLock lock = null;

        try{
            lock = redissonClient.getLock("lock"+goodsId);
            lock.lock();
            //1. 查询商品库存的数量
            String stock = template.opsForValue().get("stock"+goodsId);
            if(StringUtils.isEmpty(stock)){
                return "商品不存在";
            }
            int lastStock = Integer.parseInt(stock);
            // 2.判断库存数量是否足够
            if(lastStock<count){
                return "库存不足";
            }
            // 3. 如果库存数量足够，那么就去扣减库存
            template.opsForValue().set("stock"+goodsId,String.valueOf(lastStock-count));
            return "库存扣减成功";

        }catch (Exception e){
            throw new RuntimeException();
        } finally {
            if(lock!=null){
                lock.unlock();
            }
        }

    }


}
